package ua.yandex.lockfree;

import static java.lang.Thread.sleep;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;

public class LockFreePower {

    private final AtomicReference<BigInteger> current;
    private ArrayList result;

    LockFreePower() {
        this.current = new AtomicReference<>(BigInteger.ONE);
    }

    BigInteger next() {
        BigInteger value = null;
        while (true) {
            value = current.get();
            BigInteger newValue = value.shiftLeft(1);
            if (current.compareAndSet(value, newValue)) {
                break;
            }
        }
        return value;
    }

    public synchronized boolean wasCreatedWithoutRepition(final int size)
            throws InterruptedException {
        final int SLEEP = 5;
        result = new ArrayList();
        ExecutorService s = Executors.newCachedThreadPool();
        Task task = new Task();
        for (int i = 0; i < size; i++) {
            s.submit(task);
        }
        while (size != result.size()) {
            sleep(SLEEP);
        }
        MyComparator c = new MyComparator();
        result.sort(c);
        BigInteger number = BigInteger.ONE;
        for (int i = 0; i < size; i++) {
            if (!number.equals(result.get(i))) {
                return false;
            }
            number = number.shiftLeft(1);
        }
        return true;
    }

    private class Task implements Runnable {

        @Override
        public void run() {
            BigInteger temp = next();
            synchronized (this) {
                result.add(temp);
            }
        }
    }

    private class MyComparator implements Comparator {

        @Override
        public int compare(Object a, Object b) {
            return (((Comparable) a).compareTo(b));
        }
    }
}
